/*
 * Copyright (C) 2018 The Asiainfo-Ability Authors
 *
 *      Licensed under the Apache License, Version 2.0 (the "License");
 *      you may not use this file except in compliance with the License.
 *      You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *      Unless required by applicable law or agreed to in writing, software
 *      distributed under the License is distributed on an "AS IS" BASIS,
 *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *      See the License for the specific language governing permissions and
 *      limitations under the License.
 */

package org.asiainfo.ability.gateway.configuration;

import org.asiainfo.ability.gateway.custom.CustomHttpClientRibbonCommandFactory;
import org.asiainfo.ability.gateway.custom.CustomRouteLocator;
import org.asiainfo.ability.gateway.custom.CustomSimpleHostRoutingFilter;
import org.asiainfo.ability.gateway.filter.*;
import org.asiainfo.ability.gateway.service.AbilityGatewayFacade;
import org.asiainfo.ability.gateway.service.support.AbilityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.commons.httpclient.ApacheHttpClientConnectionManagerFactory;
import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandFactory;
import org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter;
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.util.UrlPathHelper;

import java.util.Collections;
import java.util.Set;

@Configuration
public class ZuulConfig {
    @Autowired
    ZuulProperties zuulProperties;
    @Autowired
    ServerProperties server;

    @Autowired
    AbilityService abilityService;

    @Bean
    public CustomRouteLocator routeLocator() {
        CustomRouteLocator routeLocator = new CustomRouteLocator(this.server.getServletPrefix(),
                this.zuulProperties);
        routeLocator.setAbilityService(abilityService);
        return routeLocator;
    }

    //org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter
    @Autowired(required = false)
    private Set<ZuulFallbackProvider> zuulFallbackProviders = Collections.emptySet();

    @Bean
    @ConditionalOnMissingBean
    public RibbonCommandFactory<?> ribbonCommandFactory(SpringClientFactory clientFactory, ZuulProperties zuulProperties) {
        return new CustomHttpClientRibbonCommandFactory(clientFactory, zuulProperties, zuulFallbackProviders);
    }


    @Bean
    @ConditionalOnMissingBean
    public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper,
                                                           ZuulProperties zuulProperties,
                                                           ApacheHttpClientConnectionManagerFactory connectionManagerFactory,
                                                           ApacheHttpClientFactory httpClientFactory) {
        return new CustomSimpleHostRoutingFilter(helper, zuulProperties,
                connectionManagerFactory, httpClientFactory);
    }


    @Bean
    public AbilityCheckFilter checkFilterPre(AbilityGatewayFacade gatewayFacade, final RouteLocator routeLocator,
                                             final UrlPathHelper urlPathHelper) {
        return new AbilityCheckFilter(gatewayFacade, routeLocator, urlPathHelper);
    }


    @Bean
    public FinalFilter finalFilter() {
        FinalFilter finalFilter = new FinalFilter();
        finalFilter.setAbilityService(abilityService);
        return finalFilter;
    }
}